import 'dart:async';
import 'dart:convert';

import 'package:http/http.dart' as http;

import '../core.dart';
import '../model/log.dart';
import '../model/options.dart';
import 'index.dart';

/// 白名单检查以及白名单日志筛选管道
NormalLogPipe createWhitelistPipe(Core aegis) {
  bool isWhiteList = true;
  bool requestEnd = false;
  bool sendWhitelist = false;
  Timer? timer;
  List<NormalLog> pool = [];
  // config改变时主动请求白名单
  aegis.lifeCycle.on('onConfigChange', null, (ev, context) {
    timer?.cancel();
    timer = Timer(Duration(milliseconds: 500), () {
      if (sendWhitelist) {
        return;
      }
      sendWhitelist = true;
      String whiteListUrl = aegis.config.whiteListUrl;
      aegis.send(
          options: Options(url: whiteListUrl, type: SendType.whiteList),
          successCallback: (http.Response rsp) {
            requestEnd = true;
            var rspObj = jsonDecode(rsp.body);
            if (rspObj?['retcode'] == 0) {
              // 根据返回设定whitelist
              isWhiteList = rspObj?['result']?['is_in_white_list'] ?? false;

              aegis.isWhiteList = isWhiteList;
              // 熔断和请求包最大限制, issue: https://git.woa.com/TAM/Product-Prototype/issues/538
              if (rspObj?['result']?['shutdown'] == true) {
                aegis.destroy();
                return;
              }
            }
          },
          failCallback: (res) {
            requestEnd = true;
          });
    });
  });

  aegis.lifeCycle.on('destroy', null, (ev, context) {
    pool = [];
  });

  return (List<NormalLog> logs, Resolve resolve) {
    if (isWhiteList) {
      // 如在白名单，将所有的infoall转换为info类型
      List<NormalLog> formatedLog = (logs + pool).map((log) {
        formatLog(log);
        return log;
      }).toList();
      pool = []; // 清空pool中的log
      resolve(formatedLog);
    } else {
      // 不在白名单，则filter掉info类型的日志
      List<NormalLog> otherLog = logs.where((log) {
        // 除了INFO类型和API_RESPONSE类型需要判断白名单外，其他日志类型都直接上报
        if (log.level != LogType.info && log.level != LogType.apiResponse) {
          formatLog(log);
          return true;
        }
        int maxPoolLength = 200;
        if (!requestEnd) {
          pool = pool + logs;
          // 控制pool的总长度
          if (pool.length > maxPoolLength) {
            pool.removeRange(maxPoolLength, pool.length);
          }
        }
        return false;
      }).toList();
      // 判断长度避免空跑
      if (otherLog.length > 0) {
        resolve(otherLog);
      }
    }
  };
}

void formatLog(NormalLog log) {
  if (log.level == LogType.infoAll) {
    log.level = LogType.info;
  }
}
